package Part1_反射调用私有结构;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * ClassName: Demo
 * Package: IntelliJ IDEA
 * Description:
 * Written by HanXu
 * Create 2024.04.28 0:16
 */
public class ReflectionTest {
    @Test
    public void test1(){
        Person p = new Person();

        p.age=10;
        p.showAge();
    }

    @Test
    public void test2() throws InstantiationException, IllegalAccessException,
            NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
        //使用反射实现test1效果

        //创建Person类的类对象
        Class<Person> personClass = Person.class;
        //创建Person类的实例：newInstance()
        Person person = personClass.newInstance();


        //给年龄赋值
        Field ageField = personClass.getField("age");
        ageField.set(person,10);//p.age=10

        System.out.println(ageField.get(person));//10


        //给name赋值，name是private：NoSuchFieldException:name
        //Field name = personClass.getField("name");
        //name.set(person,"王大锤");


        //调用showAge方法
        Method showAgeMethod = personClass.getMethod("showAge");//后面写形参列表
        showAgeMethod.invoke(person);//后面写实参列表  age = 10

        System.out.println(person);
    }

    /**
     * 通过反射调用私有属性、方法
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws NoSuchFieldException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     */
    @Test
    public void test3() throws InstantiationException, IllegalAccessException,
            NoSuchMethodException, InvocationTargetException, NoSuchFieldException {

        //1、调用私有构造器创建实例
        //创建Person类的类对象
        Class<Person> personClass = Person.class;
        //调用私有构造器创建实例private Person(int age, String name)
        Constructor<Person> constructor = personClass.getDeclaredConstructor(int.class, String.class);

        constructor.setAccessible(true);//私有构造器获取权限
        Person person = constructor.newInstance(10, "Tom");//IllegalAccessException
        System.out.println(person);

        //2、调用私有属性
        Field name = personClass.getDeclaredField("name");
        name.setAccessible(true);//私有属性获取权限
        name.set(person,"Tim");
        System.out.println(person);

        //3、调用私有方法
        Method showName = personClass.getDeclaredMethod("showName", String.class);//参数类型写后面
        showName.setAccessible(true);//私有方法获取权限
        String invoked = (String) showName.invoke(person, "Tum");//参数写后面
        System.out.println(invoked);

        System.out.println(person);//这里的实际属性并没有修改

    }
}
